package com.xuecheng.manage_course.service;

import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.xuecheng.framework.domain.cms.CmsPage;
import com.xuecheng.framework.domain.cms.response.CmsPageResult;
import com.xuecheng.framework.domain.cms.response.CoursePreviewResult;
import com.xuecheng.framework.domain.cms.response.SysDictionaryResult;
import com.xuecheng.framework.domain.course.*;
import com.xuecheng.framework.domain.course.ext.CategoryNode;
import com.xuecheng.framework.domain.course.ext.CourseInfo;
import com.xuecheng.framework.domain.course.ext.TeachplanNode;
import com.xuecheng.framework.domain.course.request.CourseListRequest;
import com.xuecheng.framework.domain.system.SysDictionary;
import com.xuecheng.framework.exception.ExceptionCast;
import com.xuecheng.framework.model.CommCacheStr;
import com.xuecheng.framework.model.response.CommonCode;
import com.xuecheng.framework.model.response.QueryResponseResult;
import com.xuecheng.framework.model.response.QueryResult;
import com.xuecheng.framework.model.response.ResponseResult;
import com.xuecheng.manage_course.client.CmsPageClient;
import com.xuecheng.manage_course.dao.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.domain.Pageable;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.client.RestTemplate;
import sun.rmi.runtime.Log;

import javax.persistence.Column;
import javax.sound.midi.Soundbank;
import java.util.Date;
import java.util.List;
import java.util.Optional;

/**
 * @author: gongfy
 * @create: 2020/7/23 10:53
 * @Description:  课程业务层
 */
@Slf4j
@Service
public class CourseService {

    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @Autowired
    private TeachplanMapper teachplanMapper;
    @Autowired
    private CourseMapper courseMapper;
    @Autowired
    private CategoryMapper categoryMapper;
    @Autowired
    private TeachplanRepository teachplanRepository;
    @Autowired
    private CourseBaseRepository courseBaseRepository;
    @Autowired
    private CourseMarketRepository courseMarketRepository;
    @Autowired
    private CoursePicRepository coursePicRepository;
    @Autowired
    private SysDictionaryRepository sysDictionaryRepository;

    @Value("${course-publish.siteId}")
    private String publish_siteId;
    @Value("${course-publish.templateId}")
    private String publish_templateId;
    @Value("${course-publish.previewUrl}")
    private String publish_previewUrl;
    @Value("${course-publish.pageWebPath}")
    private String publish_pageWebPath;
    @Value("${course-publish.pagePhysicalPath}")
    private String publish_pagePhysicalPath;
    @Value("${course-publish.dataUrlPre}")
    private String publish_dataUrlPre;

    private static final String CATEGORY_CACHE = "categorycache";

    //查询教学计划
    public TeachplanNode selectTeachNodeList(String courseId){
        TeachplanNode teachplanNode = teachplanMapper.selectTeachNodeList(courseId);
        return teachplanNode;
    };
    //新增课程计划  todo 理解业务需求是编程的第一步
    /**
    * @Author: gongfy
    * @Param:  课程计划信息teachplan
    * @Return:  响应结果
    * @Date: 2020/7/25 16:17
    * @Description: 添加课程计划信息  重点：处理parentId  根节点：one_id,二级节点two_id,三级节点 three_id
     * 1.上级节点 不填就表示根节点、
     *  todo 问题，如果不填怎么知道当前课时名称属于哪一个课程呢？  解决：可以根据传过去的courseId反查pname找到根节点，如果找不到自动生成以课程名命名的根节点
    **/
    @Transactional //操作mysql需要添加事务 Mongo不支持事务
    public ResponseResult addTeachPlan(Teachplan teachplan) {
        // 1.首先校验页面传递过来的参数
        if (teachplan == null || teachplan.getCourseid() == null || teachplan.getPname() == null){
            ExceptionCast.cast(CommonCode.INVALID_PARAM);
        }
        //

        String courseid = teachplan.getCourseid();
        // 判断是否存在上级节点  存在：  不存在：需要取出当前课程的根节点
        String parentid = teachplan.getParentid();
        if (StringUtils.isEmpty(parentid)){ // 不存在
            //取出当前课程的根节点  存在： 不存在：如果查询不到自动添加根节点
            parentid = this.getTeachplanRoot(courseid);
        }
        //取出父节点信息
        Optional<Teachplan> optionalTeachplan = teachplanRepository.findById(parentid);
        if (!optionalTeachplan.isPresent()){
            ExceptionCast.cast(CommonCode.INVALID_PARAM);
        }
        //父节点
        Teachplan teachplanParent = optionalTeachplan.get();
        //设置级别(根据父节点级别)
        String parentGrade = teachplanParent.getGrade();
        //需要保存的新节点
        Teachplan teachplanNew = new Teachplan();
        //将页面提交的teachPlan信息copy到teachplanNew中去
        BeanUtils.copyProperties(teachplan,teachplanNew);
        if ("1".equals(parentGrade)){
            teachplanNew.setGrade("2");
        }else {
            teachplanNew.setGrade("3");
        }
        //设置父节点
        teachplanNew.setParentid(parentid);
        //设置设置课程id
        teachplanNew.setCourseid(teachplanParent.getCourseid());
        // 保存课程计划信息
        teachplanRepository.save(teachplanNew);
        //清除redis缓存
//        redisTemplate.boundHashOps().put("categoryList",null);
//        redisTemplate.opsForValue().set("categorystring",null);
        return new ResponseResult(CommonCode.SUCCESS);
    }

    //取出单签课程的根节点  存在： 不存在：自动添加根节点信息
    private String getTeachplanRoot(String courseId){
        List<Teachplan> teachplanList = teachplanRepository.findByCourseidAndParentid(courseId, "0");
        if (teachplanList == null || teachplanList.size()<=0){  // todo  待测试不存在根节点情况 新增课程后可测试该节点
            //查询不到根节点 则以当前课程名称作为根节点名称 保存新的课程计划信息 此处要先反查当前课程信息
            Optional<CourseBase> courseBaseOptional = courseBaseRepository.findById(courseId);
            if (!courseBaseOptional.isPresent()){
                return null;
            }
            CourseBase courseBase = courseBaseOptional.get();
            Teachplan teachplan = new Teachplan();
            teachplan.setParentid("0");
            teachplan.setGrade("1");
            teachplan.setPname(courseBase.getName());
            teachplan.setStatus("0");
            teachplan.setCourseid(courseId);
            Teachplan save = teachplanRepository.save(teachplan);
            return save.getId(); // 保存成功返回新添加的根节点id
        }
        //返回根节点id
        return teachplanList.get(0).getId();
    }

    //课程查询
    public QueryResponseResult findCourseList(int page, int size, CourseListRequest courseListRequest) {

        //1.设置分页参数
        PageHelper.startPage(page, size);
        //2.执行查询  todo PageHelper mybatis分页插件使用courseMapper 不是用JPA的courseBaseRepository.findAll()
        Page<CourseBase> courseBase = courseMapper.findAllCourseBase();
        //3.封装查询结果
        QueryResult<CourseBase> courseBaseQueryResult  = new QueryResult<>();
        courseBaseQueryResult.setTotal(courseBase.getTotal());
        courseBaseQueryResult.setList(courseBase.getResult());
        //4.返回响应结果
        return new QueryResponseResult(CommonCode.SUCCESS,courseBaseQueryResult);
    }

    public ResponseResult addCourse(CourseBase courseBase) {

        // 1.新增之前先查询 判断是否存在
        Optional<CourseBase> optionalCourseBase = courseBaseRepository.findById(courseBase.getId());
        if (optionalCourseBase.isPresent()){
            ExceptionCast.cast(CommonCode.COURSEBASE_EXISTS);
        }
        // 2. 创建课程类用以保存
        CourseBase course = new CourseBase();
        course.setName(courseBase.getName());//课程名称
        course.setUsers(courseBase.getUsers());//适用人群
        course.setMt(courseBase.getMt()); //课程分类 大类
        course.setSt(courseBase.getSt()); //课程分类 小类
        course.setGrade(courseBase.getGrade()); //课程等级
        course.setStudymodel(courseBase.getStudymodel()); //学习模式
        course.setDescription(courseBase.getDescription());//课程介绍
        courseBaseRepository.save(course);
        return new ResponseResult(CommonCode.SUCCESS);
    }

    //查询课程等级、学习模式
    public SysDictionary findCourseGrade(String dType) {
        List<SysDictionary> sysDictionary = sysDictionaryRepository.findSysDictionaryByDType(dType);
        if (sysDictionary == null || sysDictionary.size() <=0){
            ExceptionCast.cast(CommonCode.FAIL);
        }
        // todo 返回  new SysDictionaryResult(CommonCode.SUCCESS,sysDictionary.get(0)); 为什么不行
        return sysDictionary.get(0);
    }

    // 课程分类查询
    public CategoryNode findCategoryList() {
        //查询redis  todo 对应的增删改操作都要添加更新reids操作
        //CategoryNode categoryNodeCache = (CategoryNode)redisTemplate.boundHashOps(CATEGORY_CACHE).get("categoryList");
        CategoryNode categoryCacheStr= (CategoryNode)redisTemplate.opsForValue().get("categorystring");
        if (categoryCacheStr != null){
            log.info("从缓存中获取categoryList："+ categoryCacheStr);
            return categoryCacheStr;
        }
        CategoryNode categoryList = categoryMapper.findCategoryList();
        //放入缓存
        //redisTemplate.boundHashOps(CATEGORY_CACHE).put("categoryList",categoryList);
        RedisSerializer redisSerializer = new StringRedisSerializer();
        redisTemplate.setKeySerializer(redisSerializer);
        //redisTemplate.setValueSerializer(new RedisSerializer());
        //redisTemplate.setStringSerializer(redisSerializer);
        redisTemplate.opsForValue().set("categorystring",categoryList);

        log.info("从数据库中获取categoryList："+ categoryList);
        return categoryList;
    }

    // 根据课程id查询
    public CourseBase findCourseBaseById(String courseId) {
        return courseMapper.findCourseBaseById(courseId);
    }

    //修改课程信息
    public ResponseResult updateCoursebase(CourseBase courseBase) {
        CourseBase course = courseMapper.findCourseBaseById(courseBase.getId());  // jpa也可以查询
        if (course == null){
            ExceptionCast.cast(CommonCode.COURSEBASE_NOTEXISTS);
        }

        //封装信息
        course.setName(courseBase.getName());//课程名称
        course.setUsers(courseBase.getUsers());//适用人群
        course.setMt(courseBase.getMt()); //课程分类 大类
        course.setSt(courseBase.getSt()); //课程分类 小类
        course.setGrade(courseBase.getGrade()); //课程等级
        course.setStudymodel(courseBase.getStudymodel()); //学习模式
        course.setDescription(courseBase.getDescription());//课程介绍

        courseBaseRepository.save(course);
        return new ResponseResult(CommonCode.SUCCESS);

    }

    // 获取课程营销信息
    public CourseMarket getCourseMarketById(String id) {
        Optional<CourseMarket> optionalCourseMarket = courseMarketRepository.findById(id);
        if (!optionalCourseMarket.isPresent()){
            ExceptionCast.cast(CommonCode.FAIL);
        }
        return optionalCourseMarket.get();
    }

    //修改课程营销信息
    public ResponseResult updateCourseMarket(CourseMarket courseMarket) {
        //不查询了，直接修改吧。
        CourseMarket savecourseMarket = new CourseMarket();
        savecourseMarket.setCharge(courseMarket.getCharge()); //收费规则，对应数据字典
        savecourseMarket.setPrice(courseMarket.getPrice()); //价格
        savecourseMarket.setStartTime(courseMarket.getStartTime()); //课程有效期-开始时间
        savecourseMarket.setEndTime(courseMarket.getEndTime()); //课程有效期-结束时间
        savecourseMarket.setQq(courseMarket.getQq()); //咨询QQ
        courseMarketRepository.save(savecourseMarket);
        return new ResponseResult(CommonCode.SUCCESS);
    }

    //课程视图查询，包括基本信息、图片、营销、课程计划
    public CourseView findCourseView(String id) {

        CourseView courseView = new CourseView();
        //1.课程基础信息查询
        Optional<CourseBase> optionalCourseBase = courseBaseRepository.findById(id);
        if (optionalCourseBase.isPresent()){
            courseView.setCourseBase(optionalCourseBase.get());
        }
        //2.课程营销信息查询
        Optional<CourseMarket> optionalCourseMarket = courseMarketRepository.findById(id);
        if (optionalCourseMarket.isPresent()){
            courseView.setCourseMarket(optionalCourseMarket.get());
        }
        //3.课课程图片查询
        Optional<CoursePic> optionalCoursePic = coursePicRepository.findById(id);
        if (optionalCoursePic.isPresent()){
            courseView.setCoursePic(optionalCoursePic.get());
        }
        //4.教学计划查询
        TeachplanNode teachplanNode = teachplanMapper.selectTeachNodeList(id);
        courseView.setTeachplanNode(teachplanNode);
        return courseView;

    }

    @Autowired
    private CmsPageClient cmsPageClient;
    //课程预览
    public CoursePreviewResult preview(String courseId) {
        //1.远程请求cms添加页面
        CourseBase courseBase = courseMapper.findCourseBaseById(courseId);
        log.info("课程预览courseBase:"+courseBase);
        CmsPage cmsPage = new CmsPage();
        cmsPage.setSiteId(publish_siteId);
        cmsPage.setTemplateId(publish_templateId);
        cmsPage.setPageWebPath(publish_pageWebPath);
        cmsPage.setPageName(courseId+".html");
        cmsPage.setPageAliase(courseBase.getName());
        cmsPage.setPagePhysicalPath(publish_pagePhysicalPath);
        cmsPage.setDataUrl(publish_dataUrlPre+courseId);
        //远程调用保存页面
        CmsPageResult cmsPageResult = cmsPageClient.savePage(cmsPage);
        if (!cmsPageResult.isSuccess()){
            return new CoursePreviewResult(CommonCode.FAIL,null);
        }
        //2.拼装页面预览的url
        String pageId = cmsPageResult.getCmsPage().getPageId();
        String pageUrl = publish_previewUrl + pageId;
        //3.返回CoursePreviewResult对象给前端（内含预览的url）
        return new CoursePreviewResult(CommonCode.SUCCESS,pageUrl);
    }
}
